using System;
using System.IO;
using PTP.Core;
using System.Collections;

namespace PTP.Devices
{
  /// <summary>
  /// Factory class that can be used to create IPTPDevice objects
  /// </summary>
  public class DeviceFactory
  {
    private static DeviceFactory _instance = null;
    /// <summary>
    /// Get DeviceFactory singleton
    /// </summary>
    public static DeviceFactory Instance
    {
      get
      {
        if (_instance == null)
          _instance = new DeviceFactory();
        return _instance;
      }
    }

    /// <summary>
    /// Create new DeviceFactory with default device adapters
    /// </summary>
    protected DeviceFactory()
    {
      this.registerDefaultAdapters();
    }

    /// <summary>
    /// Registered adapters
    /// </summary>
    protected ArrayList adapters = null;

    /// <summary>
    /// Register device adapter that is used when new device is created
    /// </summary>
    /// <param name="adapter">IDeviceAdapter object</param>
    public void RegisterAdapter(IDeviceAdapter adapter)
    {
      if (this.adapters == null)
        this.adapters = new ArrayList();
      this.adapters.Add(adapter);
    }

    /// <summary>
    /// Registers default adapters
    /// </summary>
    protected void registerDefaultAdapters()
    {
      this.RegisterAdapter(new CanonEOSAdapter());
    }

    /// <summary>
    /// Creates device that uses given stream for PTP communication
    /// </summary>
    /// <param name="s">The stream for PTP communication</param>
    /// <returns>IPTPDevice object for the connected device</returns>
    public IPTPDevice CreateDevice(Stream s)
    {
      ContainerStream stream = new ContainerStream(s);
      GenericPTPDevice genericDevice = new GenericPTPDevice(stream);
      DeviceInfo info = genericDevice.GetDeviceInfo();

      foreach (IDeviceAdapter adapter in this.adapters)
      {
        if (adapter.IsValidForDevice(info))
        {
          return adapter.CreateDevice(stream);
        }
      }
      //try with generic PTP implementation
      return genericDevice;
    }

  }
}
